﻿using System;
using System.Net;
using System.Net.Http;
using System.Net.Sockets;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Hosting.Server;
using RJCP.IO.Ports;
using ST.Core.Util;
using ST.Data;
using ST.ModelVM.ProtocolSim;
using ST.ModelVM.ProtocolSimHost;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace ST.Receiver.Tasks
{
    public class PortConnection : BaseConnection
    {
        SerialPortStream listenSocket = new SerialPortStream();
        DateTime LstOpenDt = DateTime.MinValue;
        System.Net.IPEndPoint remoteEndPoint =new System.Net.IPEndPoint(IPAddress.Any,0);
        bool _IsOpen = false;
        byte[] buffer = new byte[1024];
        public override bool Open(Data.ProtocolSim mm)
        {
            if ((DateTime.Now - LstOpenDt).TotalSeconds < 5)
            {
                return false;
            }
            LstOpenDt = DateTime.Now;
            if (listenSocket != null)
            {
                listenSocket.Dispose();
            }
            
            
            try
            {
                listenSocket = new SerialPortStream();
                listenSocket.PortName = mm.ComPort;
                listenSocket.BaudRate = mm.BaudRate;
                listenSocket.Parity = mm.Parity switch
                {
                    "None" => Parity.None,
                    "Odd" => Parity.Odd,
                    "Even" => Parity.Even,
                    "Mark" => Parity.Mark,
                    "Space" => Parity.Space,
                };
                listenSocket.DataBits = mm.DataBits;
                listenSocket.StopBits = mm.StopBits switch
                {
                    "One" => StopBits.One,
                    "OnePointFive" => StopBits.One5,
                    "Two" => StopBits.Two,

                };
                listenSocket.Open();
                _IsOpen = true;
            }
            catch
            {
                _IsOpen = false;
            }
            var msg = _IsOpen ? "成功" : "失败";
            TransMain.Instance.AddSimLog(SimWorker.Id, 0, "采集器", new byte[] { }, $"打开{SimWorker.ProtocolSim.Port} {msg}");
             
            return _IsOpen;
        }

        public override bool Close()
        {
            
            listenSocket.Close();
            listenSocket.Dispose();
            listenSocket = null;
            return true;
        }

        public override bool IsOpen()
        {
            return listenSocket!=null&& listenSocket.IsOpen;
        }

        public override int Available()
        {
            
            return listenSocket.BytesToRead;
        }
        byte[] GetSendData(ReqAndRevVM req)
        {
            req.SeqNo++;
            var  data = req.GetSendData() ;
            var senddata=new byte[data.Length+2];
            var crc16 = ST.Core.Util.ByteUtil.CalculateModbusCRC16(data, 0, data.Length);
            senddata[senddata.Length - 2] = crc16[0];
            senddata[senddata.Length - 1] = crc16[1];
            Buffer.BlockCopy(data, 0, senddata, 0, data.Length);
            return senddata;
        }
        byte[] GetCmdData(ReqAndRevVM req)
        {
            req.SeqNo++;
            var data = req.SendData;
            var senddata = new byte[data.Length +2];
            Buffer.BlockCopy(data, 0, senddata, 0, data.Length);
            var crc16 = ByteUtil.CalculateModbusCRC16(data, 0, data.Length  );
            senddata[senddata.Length-2] = crc16[0];
            senddata[senddata.Length - 1] = crc16[1];
             
           
            return senddata;
        }

        public override  async Task<int> SendAndRev(ProtocolSimHost  mm, ReqAndRevVM req)
        {
            var senddata = GetSendData(req);
            if (listenSocket.BytesToRead > 0)
            {
                var datatmp = new byte[listenSocket.BytesToRead];
                listenSocket.Read(datatmp);
            }
            listenSocket.Write(senddata,0,senddata.Length );
             
            req.SendLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "发送", senddata, req.SendMemo);
            var PlanRevByteCount = req.PlanRevByteCount +5;
            int Available = 0;
            for (var i = 0; i < mm.WaitTimes; i++)
            {
                var r = await SimWorker.MyDeay(mm.WaitMs);
                if (r != 0)
                {
                    req.Result = r;
                    return req.Result;
                }
                Available = this.Available();
                if (Available >= PlanRevByteCount)
                {
                    break;
                }
            }
            if (Available == 0)
            {
                req.Result = 3;
                req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", new byte[] { }, "超时");
                return req.Result;
            }

            if (Available < PlanRevByteCount)
            {
                var data1 = new byte[Available];
                listenSocket.Read(data1);
                req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", data1, "超时");
                req.Result = 3;//超时
                return req.Result;
            }

           

            var revdata =new byte[Available];
            listenSocket.Read(revdata,0,revdata.Length);    
             
             

            req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", revdata, "应答："+req.SendMemo);
             
            var crc16 = ByteUtil.CalculateModbusCRC16(revdata, 0, revdata.Length - 2);
            if (revdata[revdata.Length-2] == crc16[0] && revdata[revdata.Length - 1] == crc16[1])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "CRC16校验失败";
                req.Result = 4;//超时
                return req.Result;
            }
            if (revdata[0] == senddata[0] && revdata[ 1] == senddata[1])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "校验失败";
                req.Result = 4;//超时
                return req.Result;
            }


            var resultdata = new byte[revdata.Length - 5];
            Buffer.BlockCopy(revdata, 3, resultdata, 0, resultdata.Length);
            req.RevData = resultdata;
            req.Result = 0;
            return req.Result;

        }

        /// <summary>
        /// 发送数据  ，每个协议要跟进情况 加上 检验码 或者  流水号
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public override async Task<int> CmdAndRev(ProtocolSimHost mm, ReqAndRevVM req)
        {

            var senddata = GetCmdData(req);
            if (listenSocket.BytesToRead > 0)
            {
                var datatmp = new byte[listenSocket.BytesToRead];
                listenSocket.Read(datatmp);
            }
            listenSocket.Write(senddata, 0, senddata.Length);
             
            req.SendLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "发送", senddata, req.SendMemo);
            var PlanRevByteCount = req.PlanRevByteCount + 5 ; //TCP头6加3
            int Available = 0;
            for (var i = 0; i < mm.WaitTimes; i++)
            {
                var r = await SimWorker.MyDeayForEnd(mm.WaitMs);
                if (r != 0)
                {
                    req.Result = r;
                    return req.Result;
                }
                Available = this.Available();
                if (Available >= PlanRevByteCount)
                {
                    break;
                }
            }
            if (Available == 0)
            {
                req.Result = 3;//超时
                return req.Result;
            }
            if (Available < PlanRevByteCount)
            {
                var data0 = new byte[Available];
                listenSocket.Read(data0);
                req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", data0, "超时");
                req.Result = 3;//超时
                return req.Result;
            }


            var revdata = new byte[Available];
            listenSocket.Read(revdata);
            req.ReceiveLog = TransMain.Instance.AddSimLog(mm.ProtocolSimId, mm.Id, "接收", revdata, "应答：" + req.SendMemo);
            var crc16 = ByteUtil.CalculateModbusCRC16(revdata, 0, revdata.Length - 2);
            if (revdata[revdata.Length - 2] == crc16[0] && revdata[revdata.Length - 1] == crc16[1])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "CRC16校验失败";
                req.Result = 4;//超时
                return req.Result;
            }
            if (revdata[0] == senddata[0] && revdata[1] == senddata[1])
            {
            }
            else
            {
                req.ReceiveLog.Memo = "校验失败";
                req.Result = 4;//超时
                return req.Result;
            }

            var resultdata = new byte[revdata.Length - 5];
            Buffer.BlockCopy(revdata, 3, resultdata, 0, resultdata.Length);
            req.RevData = resultdata;
            req.Result = 0;
            return req.Result;
        }

    }
}
